package com.jmp.push;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import one.stand.advice.ResultEnum;
import one.stand.util.AssertUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class ComplexPushClient implements PushClient {
    private String DEFALUT_APPID;
    private Map<String, PushClient> clientMap = Maps.newHashMap();
    private List<String> clientAppIds = Lists.newArrayList();
    private OnePushProperties onePushProperties;

    public ComplexPushClient(OnePushProperties onePushProperties) {
        this.onePushProperties = onePushProperties;
    }

    public void addClient(PushClient pushClient) {
        AssertUtil.nonNull(pushClient.getAppId(), ResultEnum.PARAM_CHECK, "push appid must not be null");
        if (StringUtils.isBlank(DEFALUT_APPID)) {
            this.DEFALUT_APPID = pushClient.getAppId();
        }
        this.clientMap.put(pushClient.getAppId(), pushClient);
        this.clientAppIds.add(pushClient.getAppId());
    }

    @Override
    public String getAppId() {
        return this.DEFALUT_APPID;
    }

    @Override
    public List<String> getAppIds() {
        return clientAppIds;
    }

    @Override
    public String getAppId(String clientKey) {
        if (StringUtils.isBlank(clientKey)) {
            return getAppId();
        }

        OnePushProperties.OnePush onePush = onePushProperties.getClientMap().get(clientKey);
        String pushAppId = null;
        if (Objects.nonNull(onePush) && StringUtils.isNoneBlank(onePush.getAppId())) {
            pushAppId = onePush.getAppId();
        }
        return pushAppId;
    }

    @Override
    public void toOne(PushClientRequest request) {
        PushClient pushClient = getClient(request.getAppId());
        if (Objects.isNull(pushClient)) {
            return;
        }

        pushClient.toOne(request);
    }

    @Override
    public void toOneBatch(List<PushClientRequest> requests) {
        Map<String, List<PushClientRequest>> groupRequests = Maps.newHashMap();
        for (PushClientRequest pushClientRequest : requests) {
            if (groupRequests.containsKey(pushClientRequest.getAppId())) {
                groupRequests.get(pushClientRequest.getAppId()).add(pushClientRequest);
            } else {
                groupRequests.put(pushClientRequest.getAppId(), Lists.newArrayList(pushClientRequest));
            }
        }

        for (Map.Entry<String, List<PushClientRequest>> entry : groupRequests.entrySet()) {
            PushClient pushClient = getClient(entry.getKey());
            if (Objects.isNull(pushClient)) {
                continue;
            }

            pushClient.toOneBatch(entry.getValue());
        }
    }

    @Override
    public void toList(PushListRequest pushListRequest) {
        Map<String, PushListRequest> groupRequests = Maps.newHashMap();
        for (PushListRequest.PushTarget pushTarget : pushListRequest.getCids()) {
            if (groupRequests.containsKey(pushTarget.getAppId())) {
                groupRequests.get(pushTarget.getAppId()).getCids().add(pushTarget);
            } else {
                groupRequests.put(pushTarget.getAppId(), PushListRequest.builder()
                        .cids(Lists.newArrayList(pushTarget))
                        .title(pushListRequest.getTitle())
                        .content(pushListRequest.getContent())
                        .payloadContent(pushListRequest.getPayloadContent())
                        .build());
            }
        }

        for (Map.Entry<String, PushListRequest> entry : groupRequests.entrySet()) {
            PushClient pushClient = getClient(entry.getKey());
            if (Objects.isNull(pushClient)) {
                continue;
            }
            pushClient.toList(entry.getValue());
        }
    }

    @Override
    public void toAll(PushClientRequest request) {
        if (StringUtils.isNoneBlank(request.getAppId())) {
            PushClient pushClient = getClient(request.getAppId());
            if (Objects.isNull(pushClient)) {
                return;
            }

            pushClient.toAll(request);
        } else {
            for (Map.Entry<String, PushClient> entry : clientMap.entrySet()) {
                entry.getValue().toAll(request);
            }
        }
    }

    private PushClient getClient(String appId) {
        PushClient pushClient = clientMap.get(appId);
        if (Objects.isNull(pushClient)) {
            log.warn("push client is null for ({})", appId);
        }
        return pushClient;
    }
}
